﻿using System;
using System.Configuration;
using System.Reflection;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;

namespace Tibco.ServiceModel
{
    public sealed class TibcoBindingConfigurationElement : StandardBindingElement
    {
        protected override Type BindingElementType
        {
            get
            {
                return typeof(TibcoBinding);
            }
        }

        [ConfigurationProperty("deamon", IsRequired = true)]
        public string Deamon
        {
            get
            {
                return (string)base["deamon"];
            }
            set
            {
                base["deamon"] = value;
            }
        }

        [ConfigurationProperty("maxmessagesize", DefaultValue = 8192L * 10)]
        public long MaxMessageSize
        {
            get
            {
                return (long)base["maxmessagesize"];
            }
            set
            {
                base["maxmessagesize"] = value;
            }
        }

        [ConfigurationProperty("oneWay", DefaultValue = false)]
        public bool OneWayOnly
        {
            get
            {
                return (bool)base["oneWay"];
            }
            set
            {
                base["oneWay"] = value;
            }
        }

        [ConfigurationProperty("service", DefaultValue ="")]
        public string Service
        {
            get
            {
                return (string)base["service"];
            }
            set
            {
                base["service"] = value;
            }
        }

        [ConfigurationProperty("network", DefaultValue = "")]
        public string Network
        {
            get
            {
                return (string)base["network"];
            }
            set
            {
                base["network"] = value;
            }
        }

        [ConfigurationProperty("dqName", DefaultValue = "HiDM.CIM")]
        public string DQName
        {
            get
            {
                return (string)base["dqName"];
            }
            set
            {
                base["dqName"] = value;
            }
        }

        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                ConfigurationPropertyCollection properties = base.Properties;
                PropertyInfo[] propertyInfoArray = base.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
                for (int i = 0; i < (int)propertyInfoArray.Length; i++)
                {
                    PropertyInfo propertyInfo = propertyInfoArray[i];
                    object[] customAttributes = propertyInfo.GetCustomAttributes(typeof(ConfigurationPropertyAttribute), false);
                    for (int j = 0; j < (int)customAttributes.Length; j++)
                    {
                        ConfigurationPropertyAttribute configurationPropertyAttribute = (ConfigurationPropertyAttribute)customAttributes[j];
                        properties.Add(new ConfigurationProperty(configurationPropertyAttribute.Name, propertyInfo.PropertyType, configurationPropertyAttribute.DefaultValue));
                    }
                }
                return properties;
            }
        }

        [ConfigurationProperty("transactionFlow", DefaultValue = false)]
        public bool TransactionFlowEnabled
        {
            get
            {
                return (bool)base["transactionFlow"];
            }
            set
            {
                base["transactionFlow"] = value;
            }
        }

        public TibcoBindingConfigurationElement(string configurationName) : base(configurationName)
        {
        }

        public TibcoBindingConfigurationElement() : this(null)
        {
        }

        protected override void InitializeFrom(Binding binding)
        {
            base.InitializeFrom(binding);
            var TibcoBinding = binding as TibcoBinding;
            if (TibcoBinding != null)
            {
                this.Deamon = TibcoBinding.Deamon;
                this.Service = TibcoBinding.Service;
                this.Network = TibcoBinding.Network;
                this.DQName = TibcoBinding.DQName;
                this.MaxMessageSize = TibcoBinding.MaxMessageSize;
                this.OneWayOnly = TibcoBinding.OneWayOnly;
                this.TransactionFlowEnabled = TibcoBinding.TransactionFlow;
            }
        }

        protected override void OnApplyConfiguration(Binding binding)
        {
            if (binding == null)
            {
                throw new ArgumentNullException(nameof(binding));
            }
            var hostName = binding as TibcoBinding;
            if (hostName == null)
            {
                throw new ArgumentException(string.Format("Invalid type for binding. Expected {0}, Passed: {1}", typeof(TibcoBinding).AssemblyQualifiedName, binding.GetType().AssemblyQualifiedName));
            }
            hostName.Deamon = this.Deamon;
            hostName.Service = this.Service;
            hostName.Network = this.Network;
            hostName.DQName = this.DQName;
            hostName.OneWayOnly = this.OneWayOnly;
            hostName.TransactionFlow = this.TransactionFlowEnabled;
            hostName.Transport.MaxReceivedMessageSize = this.MaxMessageSize;
        }
    }
}